#define _XOPEN_SOURCE  1
#define _XOPEN_SOURCE_EXTENDED 1
#include "fileManager.h"
#include "utils.h"
#include "user.h"

/**
 * @brief ls判断参数是否合法的处理逻辑
 * @author yhx
 * @return 如果根据paramater拼接后的路径不是合法目录，则返回0，否则返回1
*/
int listDirectoryContents(char *paramater){
   // 拼接成实际的路径
   // printf("fileManager.c listDirectoryContents paramater:%s\n",paramater);
   char path[255] = {0};
   // printf("fileManager.c listDirectoryContents user.currentDirectory: %s\n",user.currentDirectory);
   stitchPaths(path,paramater);
   // printf("fileManager.c listDirectoryContents path:%s\n",path);
   // 如果该路径不是目录则失败
   // printf("fileManager.c listDirectoryContents path:%s\n",path);
   int ret = isExistThisFileOrDirectory(path);
   // printf("fileManager.c listDirectoryContents ret:%d\n",ret);
   if (ret != 1) {
      return 0;
   }

   // 如果path 是根目录的上级目录，返回0，表示失败
   if (isParentDirectory(path,"./root") == 1) {
      return 0;
   }

   return 1;
}

// cd
/**
 * @brief 根据操作拼接目录,不准在根目录cd ..
 * @return 成功返回1， 失败返回0
 */
int changeDirectory(char *paramater){
   Users userBak;
   strcpy(userBak.currentDirectory, user.currentDirectory);

   if (strchr(paramater, ' ') != NULL){
      printf("有空格\n");
      return 0;
   }

   char *token = strtok(paramater, "/");
   while (token != NULL){
      printf("userbak=%s,token=%s\n", userBak.currentDirectory, token);

      if (strcmp(token, ".") == 0){
         // 本目录，不操作
      }
      else if (strcmp(token, "..") == 0){
         // 不允许在根目录cd ..
         if (strcmp(userBak.currentDirectory, "root") == 0){
            printf("不允许根目录cd ..\n");
            return 0;
         }
         *strrchr(userBak.currentDirectory, '/') = '\0';
      }else{
         strcat(userBak.currentDirectory, "/");
         strcat(userBak.currentDirectory, token);
      }
      token = strtok(NULL, "/");
   }

   int ret = isExistThisFileOrDirectory(userBak.currentDirectory);

   // 无此目录，不能打开文件
   if (ret == -1 || ret == 0){
      printf("无此文件夹，不能打开文件\n");
      return 0;
   }

   strcpy(user.currentDirectory, userBak.currentDirectory);
   return 1;
}

// rm
/**
 * @brief 删除文件或目录
 * @return 成功返回1，失败返回0
 * @author 杨明铎
 */
int deleteOperation(char *paramater){
   if (isthisOrSuper(paramater)){
      printf("不允许在本目录删除本目录和父目录\n");
      return 0;
   }

   char path[1024];
   memset(path, 0, sizeof path);
   strcat(path, user.currentDirectory);
   strcat(path, "/");
   strcat(path, paramater);
   printf("path:%s\n", path);

   // 判断有无此目录，文件
   int ret = isExistThisFileOrDirectory(path);
   if (ret == -1){
      printf("无此文件/文件夹\n");
      return 0;
   }else if (ret == 0){

      // 删文件
      deleteFile(path);
   }else{
      // 删目录
      deleteDirectoryRecursion(path);
   }
   return 1;
}

// pwd
/**
 * @brief 返回当前目录
 * @author 杨明铎
*/
void printWorkingDirectory(int net_fd){
   
   unsigned int frameLength = strlen(user.currentDirectory);
   send(net_fd, &frameLength, sizeof frameLength, MSG_NOSIGNAL);
   send(net_fd, user.currentDirectory, frameLength, MSG_NOSIGNAL);
}

// mkdir
int makeDirectory(char *paramater){

   Users userBak;
   strcpy(userBak.currentDirectory, user.currentDirectory);

   char path[1024];
   // 拼接目录路径
   snprintf(path, sizeof(path), "%s/%s/", userBak.currentDirectory, paramater);
   DIR *dirp = opendir(path);
   if (dirp != NULL) {
      // 目录已存在
      closedir(dirp);
      printf("目录已存在\n");
      return 1;
   }

   // 目录不存在，创建新目录
   if (mkdir(path, 0777) == 0) {
      printf("目录创建成功\n");
      return 0;
   } else {
      perror("目录创建失败");
      return -1;
   }

   return 0;
}

/**
 * @brief 接收客户端上传的文件
 * @param netFd 网络连接文件描述符
 * @param *paramater 指向需要判断的文件名的指针
 * @return 返回0，接收失败，否则成功
 * @author moss
*/
int putFile(int netFd, char *paramater){
    
    char *fileName = paramater; // 文件名

    // 拼接路径
    char *pathStore = "/"; 
    char pathName[256] = {0}; 

    strcat(pathName, user.currentDirectory); 
    strcat(pathName, pathStore); 
    strcat(pathName, fileName); 

    // 打开文件
    int fileFd = open(pathName, O_RDWR|O_CREAT, 0666);

    // 接收文件大小
    off_t fileSize;
    off_t ret3 = putFileRecv(netFd, &fileSize, sizeof(off_t));
    if(ret3 == 0){ 
        return 0;
    }

    // 申请空间
    ftruncate(fileFd, fileSize);

    // 内存映射
    char *mmapFile = (char *)mmap(NULL, fileSize, PROT_READ|PROT_WRITE, MAP_SHARED, fileFd, 0);

    // 映射内容
    off_t recvFileSize = putFileRecv(netFd, mmapFile, fileSize);
    if(recvFileSize == 0){ 
        return 0;
    }

    // 文件接收不完整时，删除文件
    if(recvFileSize != fileSize){
      char *rmCommandHead = "rm ";
      char rmCommand[256] = {0};
      strcat(rmCommand, rmCommandHead);
      strcat(rmCommand, pathName);
      system(rmCommand);
    }

    // 资源清理
    munmap(mmapFile, fileSize);
    close(fileFd);

    return 0;
}


/**
 * @brief 拼接路径去当前工作目录下判断文件是否存在
 * @param parameter：要下载的文件名
*/
int isCurrentDirectoryFile(char *paramater){
   char filePath[1024];
   //拼接文件路径
   snprintf(filePath, sizeof(filePath),"%s/%s",user.currentDirectory,paramater);
   //判断文件是否存在
   if (isExistThisFileOrDirectory(filePath) == 0){
      return 1;
   }else{
      return 0;
   }
   
}
